home *** CD-ROM | disk | FTP | other *** search
-
- /*
- **
- ** $VER: msg9.c 46.1 (3.6.98)
- ** Msg9 46.1
- **
- ** m68k side of Msg9
- **
- ** Written 1997/1998 by Roland Mainz (gisburn@w-specht.rhein-ruhr.de)
- **
- */
-
- /* Msg9
- *
- * This test program reads from a file (or fills a buffer with random data)
- * and send the messages to the ppc side and shows how long this takes.
- * The Messages are send asyncronous and are re-used after they were replied
- * by the ppc side. Only a fixed number of message is used to do the transfer.
- * Each Message has a Body with a fixed size (except the last
- * message) and the PPC side checks if the msg is received correctly.
- * The whole msg body is also checked each send if it`s
- * 100% correct
- */
-
- /* amiga includes */
- #include <exec/types.h>
- #include <exec/nodes.h>
- #include <exec/lists.h>
- #include <exec/memory.h>
- #include <utility/tagitem.h>
- #include <dos/dostags.h>
- #include <PowerUP/ppclib/interface.h>
- #include <PowerUP/ppclib/memory.h>
- #include <PowerUP/ppclib/message.h>
- #include <PowerUP/ppclib/tasks.h>
-
- /* amiga prototypes */
- #include <clib/exec_protos.h>
- #include <clib/dos_protos.h>
- #include <clib/timer_protos.h>
- #include <PowerUP/clib/ppc_protos.h>
-
- /* amiga pragmas */
- #include <pragmas/exec_pragmas.h>
- #include <pragmas/dos_pragmas.h>
- #include <pragmas/timer_pragmas.h>
- #include <PowerUP/pragmas/ppc_pragmas.h>
-
- /* ANSI C includes */
- #include <stdio.h>
- #include <string.h>
-
- /* ppc example support functions */
- #include "time.h"
- #include "time_protos.h"
-
- /* project includes */
- #include "msg9.h"
-
- /******************************************************************************/
-
- /* for V45 includes compatibility */
- #ifndef MEMF_NOCACHEM68K
- #define MEMF_NOCACHEM68K MEMF_NOCACHESYNCM68K
- #endif /* !MEMF_NOCACHEM68K */
-
- /******************************************************************************/
- /* test code configuration */
-
- #define USE_FILE (1) /* 1= read from file / 0 = fill msg buffer with test pattern */
- #define MSGBODYSIZE (1024) /* size of messages */
- #define NUM_MSGS (8) /* number of transfer messages */
-
- /******************************************************************************/
-
- extern struct Library *SysBase,
- *DOSBase;
-
- /******************************************************************************/
-
- /* local prototypes */
- static LONG SeekRead( struct FileHandle *, LONG, LONG, APTR, ULONG );
-
- /******************************************************************************/
-
- /* main program entry */
- int main( void )
- {
- struct Library *PPCLibBase;
- ULONG i,
- j;
-
- Printf( "Opening ppc.library >= V44\n" );
-
- /* Note: The PPC side uses ppc.library V46-only functions
- * this side can run under V44
- */
- if( PPCLibBase = OpenLibrary( "ppc.library", 46UL ) )
- {
- #if USE_FILE
- LONG filesize = 0UL; /* file size (sum of all send blocks) */
- #else
- LONG filesize = 512 * 1024; /* size of bytes to send */
- #endif /* USE_FILE */
-
-
- #if USE_FILE
- STRPTR filename = "C:Ed"; /* A big file, should be >= 5 MB...
- * "C:Ed" is only used here because IMHO every (99.9899%)
- * Amiga has this file...
- */
- BPTR fh;
-
- Printf( "Opening test file \"%s\"\n", filename );
-
- if( fh = Open( filename, MODE_OLDFILE ) )
- {
- #endif /* USE_FILE */
- APTR MyTimerObject;
-
- Printf( "Create timer object\n" );
-
- if( MyTimerObject = TimerCreateObject() )
- {
- APTR ElfObject;
-
- Printf( "Loading PPC object\n" );
-
- if( ElfObject = PPCLoadObject( "PROGDIR:Msg9PPC.elf" ) )
- {
- APTR ReplyPort;
-
- Printf( "Creating reply port\n" );
-
- if( ReplyPort = PPCCreatePort( NULL ) )
- {
- APTR StartupMsg;
-
- if( StartupMsg = PPCCreateMessage( ReplyPort, (ULONG)sizeof( struct StartupData ) ) )
- {
- struct StartupData *StartupData;
-
- Printf( "Allocating StartupData\n" );
-
- if( StartupData = (struct StartupData *)PPCAllocVec( (ULONG)sizeof( struct StartupData ), MEMF_PUBLIC ) )
- {
- APTR Task;
-
- StartupData -> BodySize = MSGBODYSIZE;
-
- Printf( "Creating PPC task\n" );
-
- if( Task = PPCCreateTaskTags( ElfObject, PPCTASKTAG_STARTUP_MSG, (ULONG) StartupMsg,
- PPCTASKTAG_STARTUP_MSGDATA, (ULONG) StartupData,
- PPCTASKTAG_STARTUP_MSGLENGTH, sizeof( StartupData ),
- PPCTASKTAG_STARTUP_MSGID, 0UL,
- PPCTASKTAG_MSGPORT, TRUE,
- #if USE_PPC_STDIO
- PPCTASKTAG_INPUTHANDLE, (ULONG) Input(),
- PPCTASKTAG_OUTPUTHANDLE, (ULONG) Output(),
- NP_CloseInput, FALSE,
- NP_CloseOutput, FALSE,
- #endif /* USE_PPC_STDIO */
- TAG_DONE ) )
- {
- APTR PPCPort;
-
- if( PPCPort = (APTR)PPCGetTaskAttrsTags( Task, PPCTASKINFOTAG_MSGPORT, NULL, TAG_DONE ) )
- {
- signed int m;
- APTR msg[ NUM_MSGS ] = { 0 };
- UBYTE *buffer[ NUM_MSGS ] = { 0 };
- BOOL success = TRUE;
- int outstanding = 1; /* the startup message is pending... */
-
- Printf( "Allocating memory for message body\n" );
-
- for( m = 0 ; m < NUM_MSGS ; m++ )
- {
- /* Allocate a message */
- msg[ m ] = PPCCreateMessage( ReplyPort, MSGBODYSIZE );
-
- /* Allocate a message buffer. The additional 32 bytes are only for internal testing
- * NOTE: Some previous versions (e.g. V45.20) of ppc.library had a bug in the cache
- * code which caused that the ppc side sometimes got trashed messages.
- * Use MEMF_NOCACHEM68KSYNC in this case. (MEMF_NOCACHEM68K is only
- * available in V46 or higher).
- * This bug has been fixed in ppc.library V46.
- */
- buffer[ m ] = (UBYTE *)PPCAllocVec( (MSGBODYSIZE + 32), (MEMF_PUBLIC /*| MEMF_NOCACHEM68K*/) );
-
- if( (!msg[ m ]) || (!buffer[ m ]) )
- {
- success = FALSE;
- }
- }
-
- if( success )
- {
- APTR freemsg = NULL;
- UBYTE *freemsgbuffer = NULL;
- BOOL done = FALSE;
-
- m = 0; /* First unsend message... */
-
- Printf( "Sending file buffers ASYNC, check the msg validation and wait for them...\n" );
-
- { /* Begin of stopwatch block...*/
- TimerSetAttr( MyTimerObject, TIMERTAG_START );
-
- while( !done )
- {
- /* No message free ? Then try to fetch one from our "free"-pool or wait for a replied one... */
- if( freemsg == NULL )
- {
- /* Is there a message which did not see the ppc yet ? */
- if( m < NUM_MSGS )
- {
- freemsg = msg[ m ];
- freemsgbuffer = buffer[ m ];
- m++;
- }
- else
- {
- /* Wait for a message to be re-used... */
- PPCWaitPort( ReplyPort );
-
- if( freemsg = PPCGetMessage( ReplyPort ) )
- {
- freemsgbuffer = (UBYTE *)PPCGetMessageAttr( freemsg, PPCMSGTAG_DATA );
- outstanding--;
- }
- }
- }
-
- /* Any free message to send ? */
- if( freemsg )
- {
- LONG requestsize = MSGBODYSIZE,
- readsize;
-
- /* Fill the buffer */
- #if USE_FILE
- #if 0
- readsize = Read( fh, freemsgbuffer, requestsize );
- #else
- readsize = SeekRead( (struct FileHandle *)BADDR( fh ), 0L, OFFSET_CURRENT, freemsgbuffer, requestsize );
- #endif
- #else
- /* Fill buffer with "random" data */
- {
- ULONG f;
-
- if( (filesize - requestsize) <= 0L )
- {
- readsize = filesize;
- }
- else
- {
- readsize = requestsize;
- }
-
- for( f = 0 ; f < readsize ; f++ )
- {
- freemsgbuffer[ f ] = ((f - 1024) & 0xFF); /* Not a good rand replacement :-( */
- }
-
- filesize -= readsize;
- }
- #endif /* USE_FILE */
-
- /* EOF / error */
- if( readsize != requestsize )
- {
- done = TRUE;
- }
-
- /* In the error case we don't know what happed with the buffer, therefore... */
- if( readsize == -1L )
- {
- readsize = 0L;
- }
-
- #if USE_FILE
- filesize += readsize;
- #endif /* USE_FILE */
-
- /* Calc checksum (checksum -> i)... */
- for( i = 0UL, j = 0UL ; j < readsize ; j++ )
- {
- i += freemsgbuffer[ j ];
- }
-
- if( PPCSendMessage( PPCPort, freemsg, freemsgbuffer, readsize, i ) )
- {
- freemsg = NULL;
- freemsgbuffer = NULL;
- outstanding++;
- }
- else
- {
- Printf( "can't send ppc message %ld\n", (LONG)i );
- }
- }
- }
-
- TimerSetAttr( MyTimerObject, TIMERTAG_STOP );
- TimerShow( MyTimerObject );
- } /* End of stopwatch block...*/
-
- Printf( "Waiting for Task Finish Msg (Outstanding messages: %ld)...\n", (LONG)outstanding );
-
- while( outstanding > 0 )
- {
- APTR msg;
-
- if( msg = PPCGetMessage( ReplyPort ) )
- {
- outstanding--;
-
- if( msg == StartupMsg )
- {
- Printf( "Ahh..the expected Startup=Finish Msg was received.\n"
- "Now we can savely free all resources when all msgs are back.\n" );
- }
- else
- {
- #if 0
- Printf( "Some non replied Msg 0x%lx was found..wait\n", msg );
- #endif
- PPCWaitPort( ReplyPort );
- }
- }
- else
- {
- Printf( "PPCGetMessage retuned NULL\n" );
- }
- }
-
- #if USE_FILE
- Printf( "the file has %lu bytes\n", filesize );
- #endif /* USE_FILE */
- }
- else
- {
- Printf( "Couldn't allocate a message or a buffer\n" );
- }
-
- /* Get rid of the messages and their buffers */
- for( m = NUM_MSGS - 1 ; m >= 0 ; m-- )
- {
- PPCFreeVec( buffer[ m ] );
- PPCDeleteMessage( msg[ m ] );
- }
- }
- else
- {
- Printf( "Could not find the PPCTask's msgport\n" );
- }
- }
- else
- {
- Printf( "Could not create PPC task\n" );
- }
-
- PPCFreeVec( StartupData );
- }
- else
- {
- Printf( "Could not alloc Startup Data\n" );
- }
-
- PPCDeleteMessage( StartupMsg );
- }
- else
- {
- Printf( "Could not create Startup message\n" );
- }
-
- PPCDeletePort( ReplyPort );
- }
- else
- {
- Printf( "Could not create reply port\n" );
- }
-
- Printf( "Unloading PPC object\n" );
- PPCUnLoadObject( ElfObject );
- }
- else
- {
- Printf( "Could not load the elf object\n" );
- }
-
- Printf( "Disposing timer object\n" );
-
- TimerDeleteObject( MyTimerObject );
- }
- else
- {
- Printf( "Can't create timer object\n" );
- }
-
- #if USE_FILE
- (void)Close( fh );
- }
- else
- {
- Printf( "Can't open '%s' %ld\n", filename, IoErr() );
- }
- #endif /* USE_FILE */
-
- Printf( "Closing ppc.library\n" );
- CloseLibrary( PPCLibBase );
- }
- else
- {
- Printf( "Could not open ppc.library v46\n" );
- }
-
- return( RETURN_OK );
- }
-
-
- /* from mpegvideo.datatype V2.5 */
- /* This function executes a seek and read. Both DosPackets are send async that the handler process
- * can execute them as fast as possible.
- * The code avoids any memory allocation or accesses to AbsExecbase (like dos.library does).
- * Note: In the case of failure the current file position can only be obtained using a
- * Seek( fh, 0L, OFFSET_CURRENT ).
- */
- static
- LONG SeekRead( struct FileHandle *fh, LONG seek_pos, LONG seek_mode, APTR read_buffer, ULONG read_len )
- {
- LONG reslen = -1L;
- LONG error = 0L;
- struct MsgPort *mp = (&(((struct Process *)FindTask( NULL )) -> pr_MsgPort));
- struct StandardPacket seek_sp,
- read_sp;
- struct DosPacket *seek_dp = (&(seek_sp . sp_Pkt));
- struct DosPacket *read_dp = (&(read_sp . sp_Pkt));
- LONG numpkt = 0L; /* pending packets */
-
- /* Send seek (if neccesary) */
- if( !((seek_mode == OFFSET_CURRENT) && (seek_pos == 0L)) )
- {
- seek_sp . sp_Msg . mn_Node . ln_Type = NT_MESSAGE;
- seek_sp . sp_Msg . mn_Node . ln_Name = (STRPTR)seek_dp;
- seek_sp . sp_Msg . mn_Length = sizeof( struct DosPacket );
- seek_sp . sp_Pkt . dp_Link = (&(seek_sp . sp_Msg));
-
- seek_dp -> dp_Type = ACTION_SEEK;
- seek_dp -> dp_Arg1 = fh -> fh_Arg1;
- seek_dp -> dp_Arg2 = seek_pos;
- seek_dp -> dp_Arg3 = seek_mode;
-
- seek_dp -> dp_Port = seek_dp -> dp_Link -> mn_ReplyPort = mp;
- PutMsg( (fh -> fh_Type), (seek_dp -> dp_Link) );
- numpkt++;
- }
-
- /* Send read */
- read_sp . sp_Msg . mn_Node . ln_Type = NT_MESSAGE;
- read_sp . sp_Msg . mn_Node . ln_Name = (STRPTR)read_dp;
- read_sp . sp_Msg . mn_Length = sizeof( struct DosPacket );
- read_sp . sp_Pkt . dp_Link = (&(read_sp . sp_Msg));
-
- read_dp -> dp_Type = ACTION_READ;
- read_dp -> dp_Arg1 = fh -> fh_Arg1;
- read_dp -> dp_Arg2 = (LONG)read_buffer;
- read_dp -> dp_Arg3 = read_len;
-
- read_dp -> dp_Port = read_dp -> dp_Link -> mn_ReplyPort = mp;
- PutMsg( (fh -> fh_Type), (read_dp -> dp_Link) );
- numpkt++;
-
- /* Wait for outstanding msgs and fetch success/errorc codes from them */
- while( numpkt > 0L )
- {
- struct Message *msg;
-
- WaitPort( mp );
-
- while( msg = GetMsg( mp ) )
- {
- struct DosPacket *rdp = (struct DosPacket *)(msg -> mn_Node . ln_Name);
-
- /* This assumes that we only get ACTION_SEEK/ACTION_READ here back... */
- if( (rdp -> dp_Res1) == -1L )
- {
- error = rdp -> dp_Res2; /* BUG: It is not expected that a handler returns 0 here... */
- }
-
- numpkt--;
- }
- }
-
- if( !error )
- {
- reslen = read_dp -> dp_Res1;
- }
- else
- {
- SetIoErr( error );
- }
-
- return( reslen );
- }
-
-
-